using System;

namespace RapidHDL
{
	/// <summary>
	/// Truth Table lookup hashtable based on string inputs.
	/// </summary>
	public class TruthTable
	{

		System.Collections.Hashtable oTruthTable;
		string sDefaultOutput;
		int iInputWidth;
		int iOutputWidth;
		
		public TruthTable(int piInputWidth, int piOutputWidth, string psName)
		{
			sDefaultOutput = "";
			oTruthTable = new System.Collections.Hashtable();		
			iInputWidth = piInputWidth;
			iOutputWidth = piOutputWidth;
		}

		public void AddTableEntry(string psInputVector, string psOutputVector)
		{
			int iIndex;
			string sInputVector;
			char [] sNewInputVector;
			char cInput;

			if (psInputVector.ToUpper() == "DEFAULT" && psOutputVector.Length == iOutputWidth)
			{
				sDefaultOutput = psOutputVector.ToUpper();
				return;
			}

			if (psInputVector.Length != iInputWidth || psOutputVector.Length != iOutputWidth)
			{
				System.Diagnostics.Debug.Fail("Truth Table Size Mismatch");
			}
			
			sInputVector = psInputVector.ToUpper();

			for(iIndex = 0; iIndex < psInputVector.Length; iIndex++)
			{
				cInput = sInputVector[iIndex];
				if (cInput != '1' && cInput != '0' && cInput != '*')
				{
					System.Diagnostics.Debug.Fail("Invalid Truth Table Input");
				}

				if(cInput == '*')
				{
					sNewInputVector = sInputVector.ToCharArray();
					sNewInputVector[iIndex] = '0';
					this.AddTableEntry(sNewInputVector.ToString(),psOutputVector);
					sNewInputVector[iIndex] = '1';
					this.AddTableEntry(sNewInputVector.ToString(),psOutputVector);
				}
			}
			oTruthTable.Add(sInputVector,psOutputVector.ToUpper());
		}

		public string Decode(string psInput)
		{
			string sDefault = "";
			if (oTruthTable.ContainsKey(psInput))
				return (string)oTruthTable[psInput];
			else
			{
				System.Console.WriteLine(psInput.IndexOf("x"));
				if(sDefaultOutput == "" | psInput.IndexOf("x") != -1)
					return sDefault.PadRight(iOutputWidth,'x');
				else
					return sDefaultOutput;
			}
		}

		public System.Collections.Hashtable TruthTableDefinition
		{
			get{return oTruthTable;}
		}

		public string DefaultOutput
		{
			get{return sDefaultOutput;}
		}
	}
}
